package com.sy.simpleegg.platform.kkb.manager

import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.platform.kkb.bean.HeartResp
import com.sy.simpleegg.platform.kkb.bean.KkbBuyPackageResp
import com.sy.simpleegg.platform.kkb.bean.config.KkbGetPayCoinData
import com.sy.simpleegg.platform.kkb.bean.config.GetPayQrCodeData
import com.sy.simpleegg.platform.kkb.bean.good.GoodsCoinResponse
import com.sy.simpleegg.platform.kkb.bean.good.RechargeGoodsData
import com.sy.simpleegg.platform.kkb.bean.member.ConsumeCoinResult
import com.sy.simpleegg.platform.kkb.bean.member.GetMemberLoginQrCode
import com.sy.simpleegg.platform.kkb.bean.member.KkbOpenIdResponse
import com.sy.simpleegg.platform.kkb.bean.member.KkbQrCodeMemberInfoResponse
import com.sy.simpleegg.platform.kkb.bean.member.SaveCoinResult
import com.sy.simpleegg.platform.kkb.bean.pay.KkbChannelWaitOffData
import com.sy.simpleegg.platform.kkb.bean.pay.PayResult
import com.sy.simpleegg.platform.kkb.bean.pay.RepCashDataBean
import com.sy.simpleegg.platform.kkb.constant.Constant
import com.sy.simpleegg.platform.kkb.loader.BusinessLoader
import com.sy.simpleegg.platform.kkb.network.base.BaseResult
import com.sy.simpleegg.platform.kkb.signUtil.SignUtil
import com.sy.simpleegg.util.CommonUtil
import com.sy.simpleegg.util.DateTimeUtil
import com.sy.simpleegg.util.GsonUtil
import io.reactivex.Observer
import java.util.TreeMap

class KkbBusinessManager {

//    companion object {
//        var instance: IBusinessManager? = null
//    }

    private val businessLoader: BusinessLoader = BusinessLoader()

    private var isDebug = false

    private var useTestUrl = false

    companion object {
        private var instance: KkbBusinessManager? = null
            get() {
                if (field == null) {
                    field = KkbBusinessManager()
                }
                return field
            }
        @Synchronized
        fun get(): KkbBusinessManager{
            return instance!!
        }
    }

    fun getPackageList(map: MutableMap<String?, Any>, observer: Observer<BaseResult<GoodsCoinResponse?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 套餐请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.getPackageList(params, observer)
        }
//        getParamTreeMapTest()
    }

    fun getRechargeList(devNum: String, observer: Observer<BaseResult<RechargeGoodsData?>>?){
        val map: Map<String?, String?> = mapOf("DevNum" to devNum)
//        businessLoader.getRechargeList(map, observer)
    }

    fun getConfig(observer: Observer<BaseResult<KkbGetPayCoinData?>>?){
        businessLoader.getConfig(mapOf(), observer)
    }

    fun repCashData(repCashData: RepCashDataBean, observer: Observer<BaseResult<Any?>>?){
        val map = mapOf<String?, Any?>(
            Pair("TransID", repCashData.TransID),
            Pair("Count", repCashData.Count),
            Pair("Money", repCashData.Money),
            Pair("MachineBalance", repCashData.MachineBalance),
            Pair("OutStatus", repCashData.OutStatus),
            Pair("Expected", repCashData.Expected),
            Pair("SerialPortInfo", repCashData.SerialPortInfo),
            Pair("CreateTime", repCashData.CreateTime),
            Pair("Vending", repCashData.Vending),
            Pair("Msg", repCashData.Msg),
        )

        businessLoader.pullCashCoinResult(map, observer)
    }

    /**
     * 下单
     */
    fun placeOrder(map: MutableMap<String?, Any>, observer: Observer<BaseResult<KkbBuyPackageResp?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 下单请求：${GsonUtil.getInstance()?.toJson(map)}")
            businessLoader.placeOrder(params, observer)
        }

    }

    /**
     * 获取消费二维码
     */
    fun getConsumptionCode(observer: Observer<BaseResult<GetPayQrCodeData?>>?){
        val map = mapOf<String?, Any?>()
        businessLoader.getConsumptionCode(map, observer)
    }

    /**
     * 心跳
     */
    fun heart(netDelay: String, wifiStrength: String, apMac: String, mqOnline: String, observer: Observer<BaseResult<HeartResp?>>?){
        val map = mapOf<String?, Any?>(
            Pair("NetDelay", netDelay),
            Pair("WifiStrength", wifiStrength),
            Pair("APMac", apMac),
            Pair("MqOnline", mqOnline),
        )
        businessLoader.heart(map, observer)
    }

    /**
     * 查询订单支付结果
     */
    fun getPayResult(map: MutableMap<String?, Any>, observer: Observer<BaseResult<PayResult?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 查询订单支付状态请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.queryPayOrder(params, observer)
        }
    }

    /**
     * 获取登录二维码
     */
    fun getMemberLoginCode(map: MutableMap<String?, Any>, observer: Observer<BaseResult<GetMemberLoginQrCode?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 会员登录二维码请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.getMemberLoginCode(params, observer)
        }
    }

    /**
     * 查询会员扫码登录结果
     *
     */
    fun queryOpenId(map: MutableMap<String?, Any>, observer: Observer<BaseResult<KkbOpenIdResponse?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 获取OpenId请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.getOpenId(params, observer)
        }
    }

    /**
     * 查询会员扫码登录结果
     *
     */
    fun queryLgLogin(map: MutableMap<String?, Any>, observer: Observer<BaseResult<KkbQrCodeMemberInfoResponse?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 获取会员信息请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.queryLgLogin(params, observer)
        }
    }

    /**
     * 会员存币
     * @param leaguerId 会员ID
     * @param num 存币数
     * @param devNum 设备编号
     * @param remark 备注
     * @param transId 事务ID
     */
    fun repSaveCoinsData(map: MutableMap<String?, Any>, observer: Observer<BaseResult<SaveCoinResult?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 会员存币请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.repSaveCoinsData(params, observer)
        }
    }

    /**
     * 会员取币
     * @param leaguerId 会员ID
     * @param num 存币数
     * @param devNum 设备编号
     * @param remark 备注
     * @param transId 事务ID
     */
    fun repConsumeCoinsData(map: MutableMap<String?, Any>, observer: Observer<BaseResult<ConsumeCoinResult?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 会员取币请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.repConsumeCoinsData(params, observer)
        }
    }

    /**
     * 上报核销数据
     * @param leaguerId 会员ID
     * @param num 存币数
     * @param devNum 设备编号
     * @param remark 备注
     * @param transId 事务ID
     */
    fun repWriteOffData(code: String, transId: String, amount: Long, channel: String, devNum: String, isSendMq: Boolean, source: Int, observer: Observer<BaseResult<KkbChannelWaitOffData?>>?){
        val map = mapOf<String?, Any?>(
            Pair("Code", code),
            Pair("Amount", amount),
            Pair("Channel", channel),
            Pair("DevNum", devNum),
        )
        businessLoader.repWriteOffData(map, observer)
    }

    /**
     * 上报非MQ出币结果
     * @param realOutCoins 实出币数
     * @param needOutCoins 应出币数
     * @param result 出币状态： 0-成功，1-马达卡币  2-机台币不足
     * @param balance 机台余币
     * @param orderId 订单id
     * @param transId 事务id
     */
    fun repMqOutCoinResult(map: MutableMap<String?, Any>, observer: Observer<BaseResult<Any?>>?){
        getParamTreeMap(map).let { params ->
            logFile("KKB 出货结果请求：${GsonUtil.getInstance()?.toJson(params)}")
            businessLoader.repMqOutCoinResult(params, observer)
        }
    }

    /**
     * 上报非MQ出币结果
     * @param result 0 成功 其他失败
     * @param orderId 订单id
     * @param msg 错误描述
     */
    fun repNotMqOutCoinResult(result: Int, orderId: String, msg: String, observer: Observer<BaseResult<Any?>>?){
        val map = mapOf<String?, Any?>(
            Pair("Result", result),
            Pair("Message", orderId),
            Pair("OrderID", msg)
        )
        businessLoader.repOutCoinResult(map, observer)
    }

    /**
     * 组装请求参数
     */
    private fun getParamTreeMap(paramMap: Map<String?, Any?>, isAddCommon: Boolean = true): TreeMap<String, Any>{
        val tempMap: MutableMap<String, Any?> = mutableMapOf()
        val resultMap: MutableMap<String, String> = mutableMapOf()
        val unixTimestamp = DateTimeUtil.timeStapSecond()
        val nonce = CommonUtil.getUuid().replace("-", "").trim()
        if (isAddCommon){
            resultMap["appCode"] = Constant.APPCODE
            resultMap["timestamp"] = unixTimestamp
            resultMap["nonce"] = nonce
        }
        paramMap.entries.forEach { param ->
            if (param.key.isNullOrEmpty() || param.value == null){
                return@forEach
            }
            tempMap[param.key!!] = param.value
        }
        resultMap.entries.forEach { basicParam ->
            tempMap[basicParam.key] = basicParam.value
        }
        val md5SignStr = SignUtil.getSige(tempMap, if (Constant.IS_TEST) Constant.SECRET_TEST else Constant.SECRET_PRO, isAddCommon)
        resultMap["sign"] = md5SignStr
        logFile("请求参数原始数据：${GsonUtil.getInstance()?.toJson(tempMap)} sign：${GsonUtil.getInstance()?.toJson(md5SignStr)} ")
        paramMap.entries.forEach { param ->
            if (param.key.isNullOrEmpty() || param.value == null){
                return@forEach
            }
            resultMap[param.key!!] = param.value.toString()
        }
        val treeMap: TreeMap<String, Any> = TreeMap()
        resultMap.toList().sortedBy { it.first }.forEach { paramsItem ->
            treeMap.put(paramsItem.first, paramsItem.second)
        }
        return treeMap
    }

    private fun getParamTreeMapTest(isAddCommon: Boolean = true): TreeMap<String, Any>{
        val paramMap = mutableMapOf<String?, Any?>()
        paramMap["authCode"] = "E3KQDV3N"
        paramMap["mchIdentity"] = "NMNLGJIX"

        val tempMap: MutableMap<String, Any?> = mutableMapOf()
        val resultMap: MutableMap<String, String> = mutableMapOf()
        val unixTimestamp = "1583308083"
        val nonce = "498470e5d89249ef82f5197119b23678"
        if (isAddCommon){
            resultMap["appCode"] = "5PWEE6"
            resultMap["timestamp"] = unixTimestamp
            resultMap["nonce"] = nonce
        }
        paramMap.entries.forEach { param ->
            if (param.key.isNullOrEmpty() || param.value == null){
                return@forEach
            }
            tempMap[param.key!!] = param.value
        }
        resultMap.entries.forEach { basicParam ->
            tempMap[basicParam.key] = basicParam.value
        }
        val md5SignStr = SignUtil.getSige(tempMap, "EEJjC99wMpdQHncRz6misRreusgYO7Bo", isAddCommon)
        resultMap["sign"] = md5SignStr
        logFile("sign=${md5SignStr}")
        val treeMap: TreeMap<String, Any> = TreeMap()
        resultMap.toList().sortedBy { it.first }.forEach { paramsItem ->
            treeMap.put(paramsItem.first, paramsItem.second)
        }
        return treeMap
    }

}